home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / HyperCard / HC Instance Variables / Instance Variable text next >
Text File  |  1993-04-02  |  12KB  |  272 lines

  1. Instance Variables for HyperCard
  2.  
  3. by Ted Kaehler, Apple Computer, Kaehler2@AppleLink.Apple.com
  4.  
  5. Allows you to have variables attached to a button, shared field, or other HyperCard object.  Each variable can have any value that any variable in a script can have.  Names of variables may contain spaces, commas, or other special characters (enclose the variable name in double-quotes in your script).
  6.  
  7. Instance variables are useful for storing more data with a button or field.  A puzzle piece button wants to carry its home location with it.  A phone dialing button needs a place to put the local area code, without it being a constant in the middle of its script.  A background may need to carry some data useful to its scripts.
  8.  
  9. An object may have any number of variables.  Values are preserved when you quit.  They stay with your stack when you drag it to another disk.  The objects that can have variables are: a card button, a card field, the card itself, a bkgnd button, a shared field, or the background itself.  Instance variables for background fields are not supported!  This is because a background field is partly shared and partly local to the card.  When you have the urge to put a variable into a background field, attach it instead to the either the card or the current background.  
  10.  
  11. How to call:
  12.  
  13. Call  allowInstVars  once in each new background to initialize instance variables.  It creates two background fields to keep the values in.   To store into a variable, say
  14.   putVar cdBk, myID, variable, value, cardID
  15. For example, to store “East” into the variable “Direction” in the button “Engine”, say
  16.   putVar "cd", the id of card btn “Engine”, "Direction", “East”
  17.  
  18. Use the function getVar to retrieve the value of a variable: 
  19.   getVar (cdBk, myID, variable, cardID)
  20. In this case is looks like:
  21.   put getVar("cd",the id of card btn “Engine”, "Direction") into dir
  22.  
  23. The last argument, cardID is optional.  Leaving it out, as we did above, means the button on the current card.  See the script for more detail on the arguments.
  24.  
  25.  
  26. The Fine Print
  27.  
  28. The total size of all names and values or a single card cannot exceed 32K bytes.  The characters { and } may not appear in any value or variable name name.  Use with HyperCard 2.1 or later.
  29.  
  30.  
  31. The Script
  32.  
  33. This belongs in the stack script of your stack. (Just putting it in the Home script is not the best.  If you give your stack to someone, instance variables will stop working.)
  34.  
  35. -- Allow Instance Variables for buttons, fields, cards, and backgrounds.
  36. -- (c) 1991 copyright Apple Computer, all rights reserved.
  37. -- Version 1.0 for HyperCard 2.1
  38.  
  39. -- This belongs in the stack script of your stack.
  40. -- (Just putting it in the Home script is not the best.  If you then give
  41. --  your stack to someone, instance variables will stop working.)
  42.  
  43. -- You call these: putVar, getVar, allowInstVars
  44. -- Bonus handlers: removeVar, hasThisVar, allVarsOf
  45. -- Internal use only: instVar, createBkgndFld
  46.  
  47. on putVar cdBk,myID,variable,value,cardID
  48.   -- Store the value of this variable in this object
  49.   -- Example:  putVar cd,the id of me,fred,45
  50.   --    a missing cardID means on the current card
  51.   -- cdBk is cd or bk
  52.   --    (where is this object? cd is card, bk is background)
  53.   -- myID is: the short id of me
  54.   -- variable is the name under which you want to store this value
  55.   -- value is what you want to store
  56.   --   value may not contain { or } characters
  57.   -- cardID (optional) the id of the card that contains the object
  58.   
  59.   put instVar(cdBk,myID,variable,value,cardID) into dummy
  60. end putVar
  61.  
  62.  
  63. function getVar cdBk,myID,variable,cardID
  64.   -- Retrieve the value of this variable in this object
  65.   -- Example:  getVar cd,the id of me,fred
  66.   --    a missing cardID means on the current card
  67.   -- cdBk is cd or bk
  68.   --    (where is this object? cd is card, bk is background)
  69.   -- myID is: the short id of me
  70.   -- variable is the name under which you want to store this value.
  71.   --   variable may not contain { or } characters
  72.   --   it may contain spaces or other characters
  73.   -- cardID (optional) the id of the card that contains the object
  74.   
  75.   return instVar(cdBk,myID,variable,"{}",cardID)  --retrieval
  76. end getVar
  77.  
  78.  
  79. function instVar cdBk,myID,variable,value,cardID
  80.   -- Get or put the value of a variable that belongs to a
  81.   -- card button, card field, the card itself, a bkgnd button,
  82.   -- shared field, or the bkgnd itself.
  83.   
  84.   -- User should not call this. Called from getVar, putVar and removeVar.
  85.   
  86.   -- Instance variables for bkgnd fields are not supported!  This is
  87.   -- because it a background field is part shared and part local to
  88.   -- the card.  Attach the variable to the card or to a shared
  89.   -- field instead.
  90.   
  91.   -- Works for both storing and retireving, for both objects on a
  92.   -- card and object shared across a background.
  93.   
  94.   -- If value is "{}" then we are retrieving a value from the
  95.   -- dictionary.
  96.   
  97.   -- Note that myID is not enough information to actually find the
  98.   -- button or field (we don't know which it is).  But we don't
  99.   -- care.  We don't have to get at the button or field itself,
  100.   -- just find it's variables in the dictionary!
  101.   
  102.   -- The search keys
  103.   put "{" & variable & "{" & myID & "{" into startKey    --{Fred{21{
  104.   put "}" & variable & "}" & myID & "}" into endKey      --}Fred}21}
  105.   
  106.   if cardID is empty
  107.   then put the short id of this card into holder  -- on current card
  108.   else put cardID into holder   --on a specific card
  109.   
  110.   if cdBk = "bk"
  111.   then put "call allowInstVars first" into theFld  --background objects
  112.   else put "you must call allowInstVars" into theFld  --card specific
  113.   --  The names of these fields are funny so that the user will know
  114.   --  what to do when he gets and error because the fields are not there.
  115.   
  116.   -- If the field is missing, you must call allowInstVars (just once in
  117.   -- each background) to initialize some hidden fields.
  118.   put offset(startKey,bkgnd fld theFld of cd id holder) ¬
  119.   into startLoc    --loc of {Fred{21{
  120.   
  121.   if startLoc is 0 then
  122.     --the key wasn't found
  123.     if (cdBk is not "cd") and (cdBk is not "bk")
  124.     then answer "First arg of putVar must be bk or cd" with "OK"
  125.     
  126.     if value = "{}" then   --getting and it was not found
  127.       put cdBK && "id" && myID && variable && "on card id" && holder
  128.       answer "You must putVar into a variable" & return &¬
  129.       "before using getVar to read it."
  130.       return "no value in:" && variable
  131.     else
  132.       --putting a value, create a new variable
  133.       put return & startKey & value & endKey after bkgnd fld ¬
  134.       theFld of cd id holder
  135.       return value
  136.     end if
  137.   end if
  138.   
  139.   put offset(endKey,bkgnd fld theFld of cd id holder) ¬
  140.   into endLoc    --loc of }Fred}21}
  141.   
  142.   add length(startKey) to startLoc   --loc after key, start of value
  143.   subtract 1 from endLoc
  144.   if value = "{}" then   --getting a value
  145.     -- Retrieve the value of the variable
  146.     return char startLoc to endLoc of bkgnd fld theFld of cd id holder
  147.   else
  148.     if value = "re{}move" then
  149.       --remove the variable to save space
  150.       subtract length(startKey) from startLoc   --loc before key
  151.       add length(startKey) to endLoc   --loc after end key
  152.       put empty into char startLoc to endLoc of bkgnd fld ¬
  153.       theFld of cd id holder  -- remove keys and value
  154.     else
  155.       -- Store the value in the dictionary over old value
  156.       put value into char startLoc to endLoc of bkgnd fld ¬
  157.       theFld of cd id holder
  158.     end if
  159.     return value
  160.   end if
  161. end instVar
  162.  
  163. on allowInstVars
  164.   -- Create a field for the instance variable dictionary.
  165.   -- It has a funny name so the user will know what to do
  166.   -- when he gets and error because the field is not there.
  167.   createBkgndFld "you must call allowInstVars"  --card variables
  168.   createBkgndFld "call allowInstVars first"  --bkgnd variables
  169.   set sharedText of bkgnd fld "call allowInstVars first" to true
  170.   set loc of bkgnd fld "call allowInstVars first" to 160,250
  171. end allowInstVars
  172.  
  173. on createBkgndFld  theName
  174.   -- Create hidden background field if not there already.
  175.   -- Use this field for storing the dictionary of names and values.
  176.   repeat with ii = 1 to the number of bkgnd fields
  177.     put the short name of bkgnd field ii into myName
  178.     if myName is theName
  179.     then
  180.       put "already there!"
  181.       exit createBkgndFld  --already exists
  182.     end if
  183.   end repeat
  184.   
  185.   -- Create a background field for the instance variable dictionary.
  186.   doMenu "background"
  187.   doMenu "New Field"
  188.   put the number of bkgnd fields into num
  189.   set the name of field num to theName
  190.   hide field theName   -- important!
  191.   choose browse tool
  192.   doMenu "Background"    --get out of Background mode
  193.   put "new is " & num  --debugging
  194. end createBkgndFld
  195.  
  196.  
  197. -- Bonus handlers: removeVar, hasThisVar, allVarsOf
  198.  
  199. on removeVar cdBk,myID,variable,cardID
  200.   -- Remove this variable in this object
  201.   -- Is not necessary.  Only do it to save space when destroying
  202.   -- a button or other object.
  203.   -- Example:  removeVar cd,the id of me,fred
  204.   --    a missing cardID means on the current card
  205.   -- see getVar for the meaning of the arguments
  206.   
  207.   put instVar(cdBk,myID,variable,"re{}move",cardID) into data
  208.   -- this specal value means remove the variable from the dictionary
  209. end removeVar
  210.  
  211. function hasThisVar cdBk,myID,variable,cardID
  212.   -- Return true if this object has a variable of this name
  213.   -- So a script can ask if the object has one before trying to read it.
  214.   -- Example:  hasThisVar(cd,the id of me,"fred")
  215.   --    a missing cardID means on the current card
  216.   -- cdBk is cd or bk
  217.   --    (where is this object? cd is card, bk is background)
  218.   -- myID is: the short id of me
  219.   -- variable is the name under which you want to store this value
  220.   -- cardID (optional) the id of the card that contains the object
  221.   
  222.   put "{" & variable & "{" & myID & "{" into startKey    --{Fred{21{
  223.   
  224.   if cardID is empty
  225.   then put the short id of this card into holder  -- on current card
  226.   else put cardID into holder   --on a specific card
  227.   
  228.   if cdBk = "bk"
  229.   then put "call allowInstVars first" into theFld  --background objects
  230.   else put "you must call allowInstVars" into theFld  --card specific
  231.   
  232.   return offset(startKey,bkgnd fld theFld of cd id holder) is not 0
  233. end hasThisVar
  234.  
  235. function allVarsOf cdBk,myID,cardID
  236.   -- Return a list of the names of the variables in this object now.
  237.   -- Returns a list of items separated by commas
  238.   -- Example:  allVarsOf(cd,the id of me)
  239.   --    a missing cardID means on the current card
  240.   -- cdBk is cd or bk
  241.   --    (where is this object? cd is card, bk is background)
  242.   -- myID is: the short id of me
  243.   -- cardID (optional) the id of the card that contains the object
  244.   
  245.   put "{" & myID & "{" into startKey    --{21{
  246.   
  247.   if cardID is empty
  248.   then put the short id of this card into holder  -- on current card
  249.   else put cardID into holder   --on a specific card
  250.   
  251.   if cdBk = "bk"
  252.   then put "call allowInstVars first" into theFld  --background objects
  253.   else put "you must call allowInstVars" into theFld  --card specific
  254.   
  255.   put bkgnd fld theFld of cd id holder into rawData
  256.   put empty into list
  257.   repeat
  258.     put offset(startKey,rawData) into index    --{21{
  259.     if index = 0 then return list
  260.     put index-1 into ii
  261.     repeat until ii = 1    -- will not leave this way
  262.       if char ii of rawData = "{" then
  263.         if list is not empty then put "," after list
  264.         put (char ii+1 to index-1 of rawData) after list   --fred
  265.         delete char 1 to index+5 of rawData   -- remove start of this
  266.         --     variable so the next one will be the first one found
  267.       else
  268.         subtract 1 from ii  --backup one char
  269.       end if
  270.     end repeat
  271.   end repeat
  272. end allVarsOf